package club.xyes.zkh.ecommerce.web.api.controller;

import club.xyes.zkh.ecommerce.commons.dto.Tuple2;
import club.xyes.zkh.ecommerce.commons.entity.Shop;
import club.xyes.zkh.ecommerce.commons.entity.ShopMembership;
import club.xyes.zkh.ecommerce.commons.entity.ShopMembershipLevel;
import club.xyes.zkh.ecommerce.commons.exception.BadRequestException;
import club.xyes.zkh.ecommerce.commons.util.TextUtil;
import club.xyes.zkh.ecommerce.commons.vo.GeneralCollectionResult;
import club.xyes.zkh.ecommerce.commons.vo.GeneralResult;
import club.xyes.zkh.ecommerce.service.ShopMembershipLevelService;
import club.xyes.zkh.ecommerce.service.ShopMembershipService;
import club.xyes.zkh.ecommerce.service.ShopService;
import club.xyes.zkh.ecommerce.web.controller.BaseController;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Create by 郭文梁 2019/4/18 0018 14:49
 * ShopMembershipLevelController
 * 商铺会员等级定义相关数据访问控制器
 *
 * @author 郭文梁
 * @data 2019/4/18 0018
 */
@RestController
@RequestMapping("/api/level")
public class ShopMembershipLevelController extends BaseController<ShopMembershipLevel> {
    private final ShopMembershipLevelService service;
    private final ShopMembershipService shopMembershipService;
    private final ShopService shopService;

    @Autowired
    public ShopMembershipLevelController(ShopMembershipLevelService service,
                                         ShopMembershipService shopMembershipService,
                                         ShopService shopService) {
        super(service);
        this.service = service;
        this.shopMembershipService = shopMembershipService;
        this.shopService = shopService;
    }

    /**
     * 获取会员卡的等级定义
     *
     * @param membershipId 会员卡ID
     * @return GR
     */
    @GetMapping("/membership/{membershipId}")
    @ApiOperation("获取指定会员卡的等级定义")
    public GeneralCollectionResult<ShopMembershipLevel> byMembershipId(@PathVariable("membershipId") Integer membershipId) {
        List<ShopMembershipLevel> levels = service.findByMembershipId(membershipId);
        return GeneralCollectionResult.ok(levels);
    }

    /**
     * 为会员卡创建新的会员等级
     *
     * @param membershipId 会员卡ID
     * @param param        会员等级
     * @return GR
     */
    @PostMapping("/membership/{membershipId}")
    @ApiOperation("为会员卡创建新的等级")
    public GeneralResult<?> create(@PathVariable("membershipId") Integer membershipId,
                                   @RequestBody ShopMembershipLevel param) {
        checkParam(param);
        ShopMembership membership = shopMembershipService.getRequired(membershipId);
        checkConditions(membership, param);
        Shop shop = currentShop();
        if (!Objects.equals(shop.getId(), membership.getShopId())) {
            return GeneralResult.permissionDenied("您无权操作该数据");
        }
        ShopMembershipLevel level = new ShopMembershipLevel();
        level.setMembership(membership);
        level.setShopMembershipId(membershipId);
        level.setName(param.getName());
        level.setLevelValue(param.getLevelValue());
        level.setConditionMode(param.getConditionMode());
        level.setConditionAmount(param.getConditionAmount());
        level.setConditionTimes(param.getConditionTimes());
        level.setDiscountRate(param.getDiscountRate());
        level.setState(ShopMembershipLevel.STATE_ENABLE);
        ShopMembershipLevel res = service.save(level);
        return GeneralResult.ok(res);
    }

    /**
     * 检查等级条件参数
     *
     * @param membership 会员
     * @param param      参数
     */
    private void checkConditions(ShopMembership membership, ShopMembershipLevel param) {
        List<ShopMembershipLevel> levels = service.findByMembershipId(membership.getId());
        Optional<Tuple2<Integer, Integer>> maxConditionOptional = levels.stream()
                .map(v -> Tuple2.of(v.getConditionAmount(), v.getConditionTimes()))
                .map(v -> {
                    Integer amount;
                    try {
                        amount = Integer.parseInt(v.getO1());
                    } catch (NumberFormatException e) {
                        amount = null;
                    }
                    return Tuple2.of(amount, v.getO2());
                })
                .reduce((v1, v2) -> {
                    Integer maxAmount;
                    if (v1.getO1() == null) {
                        maxAmount = v2.getO1();
                    } else if (v2.getO1() == null) {
                        maxAmount = v1.getO1();
                    } else {
                        maxAmount = v1.getO1() > v2.getO1() ? v1.getO1() : v2.getO1();
                    }
                    Integer maxTimes;
                    if (v1.getO2() == null) {
                        maxTimes = v2.getO2();
                    } else if (v2.getO2() == null) {
                        maxTimes = v1.getO2();
                    } else {
                        maxTimes = v1.getO2() > v2.getO2() ? v1.getO2() : v2.getO2();
                    }
                    return Tuple2.of(maxAmount, maxTimes);
                });
        if (!maxConditionOptional.isPresent()) {
            return;
        }
        Tuple2<Integer, Integer> maxCondition = maxConditionOptional.get();
        switch (param.getConditionMode()) {
            case ShopMembershipLevel.CONDITION_MODE_BOTH:
            case ShopMembershipLevel.CONDITION_MODE_ONLY_FEE:
                if (param.getConditionAmount() != null && Integer.parseInt(param.getConditionAmount()) < maxCondition.getO1()) {
                    throw new BadRequestException("消费金额必须大于上一次的定义");
                }
            default:
                // Do nothing
        }
        switch (param.getConditionMode()) {
            case ShopMembershipLevel.CONDITION_MODE_BOTH:
            case ShopMembershipLevel.CONDITION_MODE_ONLY_TIMES:
                if (param.getConditionTimes() != null && param.getConditionTimes() < maxCondition.getO2()) {
                    throw new BadRequestException("消费次数必须大于上一次的定义");
                }
            default:
                //Do nothing
        }
        if (Objects.equals(param.getConditionMode(), ShopMembershipLevel.CONDITION_MODE_OR)) {
            if (param.getConditionAmount() == null && param.getConditionTimes() == null) {
                throw new BadRequestException("请输入消费金额或消费次数至少一项");
            }
        }
    }


    /**
     * 更新等级定义信息
     *
     * @param id    等级ID
     * @param param 参数
     * @return GR
     */
    @PostMapping("/{id}")
    @ApiOperation("更新等级定义信息")
    public GeneralResult<ShopMembershipLevel> update(@PathVariable("id") Integer id,
                                                     @RequestBody ShopMembershipLevel param) {
        checkParam(param);
        ShopMembershipLevel membershipLevel = service.getRequired(id);
        ShopMembership membership = shopMembershipService.getRequired(membershipLevel.getShopMembershipId());
        Shop shop = currentShop();
        if (!Objects.equals(membership.getShopId(), shop.getId())) {
            return GeneralResult.permissionDenied("你无权操作该数据");
        }
        membershipLevel.setMembership(membership);
        membershipLevel.setName(param.getName());
        membershipLevel.setLevelValue(param.getLevelValue());
        membershipLevel.setConditionMode(param.getConditionMode());
        membershipLevel.setConditionAmount(param.getConditionAmount());
        membershipLevel.setConditionTimes(param.getConditionTimes());
        membershipLevel.setDiscountRate(param.getDiscountRate());
        ShopMembershipLevel res = service.updateById(membershipLevel);
        return GeneralResult.ok(res);
    }

    /**
     * 请用、禁用等级
     *
     * @param id    ID
     * @param param {state:1}
     * @return GR
     */
    @ApiOperation("启用、禁用等级")
    @PostMapping("/{id}/operate")
    public GeneralResult<ShopMembershipLevel> operate(@PathVariable("id") Integer id,
                                                      @RequestBody ShopMembershipLevel param) {
        if (param == null || param.getState() == null) {
            return GeneralResult.badRequest("缺少参数");
        }
        ShopMembershipLevel membershipLevel = service.getRequired(id);
        membershipLevel.setState(param.getState());
        ShopMembershipLevel res = service.updateById(membershipLevel);
        return GeneralResult.ok(res);
    }

    /**
     * 检查参数
     *
     * @param param 参数
     */
    private void checkParam(ShopMembershipLevel param) {
        checkConditionMode(param);
        if (TextUtil.isTrimedEmpty(param.getName())) {
            throw new BadRequestException("等级名称不能为空");
        }
        if (param.getLevelValue() == null) {
            throw new BadRequestException("等级不能为空");
        }
        try {
            Double.parseDouble(param.getDiscountRate());
        } catch (Exception e) {
            throw new BadRequestException("折扣率不合法", e);
        }
    }

    /**
     * 检查德吉获取条件是否合法
     *
     * @param param 参数
     */
    private void checkConditionMode(ShopMembershipLevel param) {
        Integer mode = param.getConditionMode();
        if (mode == null) {
            throw new BadRequestException("等级条件不能为空");
        }
        Integer conditionTimes = param.getConditionTimes();
        Integer conditionAmount;
        try {
            conditionAmount = Integer.parseInt(param.getConditionAmount());
        } catch (Exception e) {
            conditionAmount = null;
        }
        switch (mode) {
            case ShopMembershipLevel.CONDITION_MODE_BOTH:
                if (conditionAmount == null || conditionTimes == null) {
                    throw new BadRequestException("消费金额和消费次数都不能为空");
                }
                break;
            case ShopMembershipLevel.CONDITION_MODE_OR:
                if (conditionAmount == null && conditionTimes == null) {
                    throw new BadRequestException("请保证消费金额和消费次数其中一个不为空");
                }
                break;
            case ShopMembershipLevel.CONDITION_MODE_ONLY_FEE:
                if (conditionAmount == null) {
                    throw new BadRequestException("消费金额不能为空");
                }
                break;
            case ShopMembershipLevel.CONDITION_MODE_ONLY_TIMES:
                if (conditionTimes == null) {
                    throw new BadRequestException("消费次数不能为空");
                }
                break;
            default:
                throw new BadRequestException("等级条件 " + mode + " 不合法");
        }
    }

    /**
     * 获取当前用户所拥有的店铺
     *
     * @return 店铺
     */
    private Shop currentShop() {
        return currentShop(shopService);
    }

    /**
     * 获取当前商铺的会员信息
     *
     * @return 会员信息
     */
    @GetMapping("/by-current-shop")
    @ApiOperation("当前商铺的会员等级")
    public GeneralResult<List<Map<String, Object>>> findByShopId() {
        Shop shop = currentShop();
        List<ShopMembership> memberships = shopMembershipService.findByShop(shop);
        List<Map<String, Object>> res = memberships.stream().map(m -> {
            List<ShopMembershipLevel> levels = service.findByMembershipId(m.getId());
            Map<String, Object> item = new HashMap<>(2);
            item.put("membership", m);
            item.put("levels", levels);
            return item;
        }).collect(Collectors.toList());
        return GeneralResult.ok(res);
    }
}
